package com.cangshi.permission.session.entity;

import com.alibaba.fastjson.JSON;
import com.cangshi.permission.entity.*;
import com.cangshi.permission.holder.CurrentHolder;
import com.cangshi.permission.session.exception.SessionCannotFindException;
import com.cangshi.permission.session.exception.SessionIdCannotFindException;
import com.cangshi.permission.session.exception.SessionIsDisabledException;

import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by Eoly on 2017/4/17.
 */
public abstract class SessionSources extends ObjectSources {

    private SessionCacheManager sessionCacheManager;

    protected abstract LoginResult checkForLogin(Token token);

    protected UserSubject.CheckAndBuild checkAndBuild(final Token token) {
        final LoginResult loginResult = checkForLogin(token);

        return new UserSubject.CheckAndBuild() {
            @Override
            protected Boolean setCheckResult() {
                return loginResult.getLoginPass();
            }

            @Override
            protected AuthorizationEntity setBuildResult() {
                AuthorizationEntity authorizationEntity = new SessionAuthorizationEntity();
                if (sessionCacheManager.getSingleSignOn()
                        && loginResult.getIdentificationKey() != null) {

                    // 单点登录判断(遍历查询)
                    List<String> sessionIds = sessionCacheManager.getSessionIdList();
                    System.out.println("----------->" + JSON.toJSONString(sessionIds));
                    if (sessionIds != null) {
                        for (String id : sessionIds) {
                            Session<String, Object> checkSession = sessionCacheManager.getSession(id);
                            if (loginResult.getIdentificationKey().equals(
                                    checkSession.getIdentificationKey()
                            )) {
                                // 设置前一个session失效(强制下线)
                                checkSession.setOnline(false);
                                break;
                            }
                        }
                    }

                }
                // 在对话缓存区中创建一个session，并将其sessionId添加到证书实体中
                String sessionId = sessionCacheManager.addSession();
                if (sessionCacheManager.getSingleSignOn() && loginResult.getIdentificationKey() != null) {
                    Session<String, Object> resultSession = sessionCacheManager.getSession(sessionId);
                    resultSession.setIdentificationKey(loginResult.getIdentificationKey());
                }
                // 获取用户自定义的session属性
                Map<String, Object> sessionMap = loginResult.getSessionMap();
                // 解析用户存入的session对象
                if (sessionMap.size() > 0) {
                    for (Map.Entry<String, Object> entry : sessionMap.entrySet()) {
                        sessionCacheManager.addSessionAttribute(sessionId, entry.getKey(), entry.getValue());
                    }
                }
                // 将获取的sessionId和用户权限与证书实体绑定
                ((SessionAuthorizationEntity) authorizationEntity)
                        .setSessionId(sessionId);
                authorizationEntity.setPermissionKey(loginResult.getPermissionKey());
                return authorizationEntity;
            }
        };
    }

    protected Boolean checkAuthorizationEntity(AuthorizationEntity entity) {

        // 获取用户整数中的会话id
        // System.out.println("----------->"+ JSON.toJSONString(entity));
        String sessionId = ((SessionAuthorizationEntity) entity).getSessionId();
        if (sessionId == null) {
            throw new SessionIdCannotFindException("证书会话id不存在");
        }
        // 从缓存中查找该用户证书所对应的会话
        Session<String, Object> session = sessionCacheManager.getSession(sessionId);

        if (null == session) {
            throw new SessionCannotFindException("未找到证书会话id对应的会话");
        }

        // 验证该用户是否在他处登录
        if (sessionCacheManager.getSingleSignOn()) {
            System.out.println(">>>>>>>session:" + JSON.toJSONString(session));
            if (!session.getOnline()) {
                sessionCacheManager.removeSession(sessionId);
                throw new SessionIsDisabledException("该用户会话因在他处登录而下线");
            }
        }

        // 将session存入当前用户对象
        UserSubject subject = (UserSubject) CurrentHolder.getSubject();
        subject.setSession(session);
        CurrentHolder.setSubject(subject);

        return true;
    }

    public SessionCacheManager getSessionCacheManager() {
        return sessionCacheManager;
    }

    public void setSessionCacheManager(SessionCacheManager sessionCacheManager) {
        this.sessionCacheManager = sessionCacheManager;
    }

    public class LoginResult {
        private Boolean isLoginPass;
        private Integer permissionKey;
        private Map<String, Object> sessionMap;
        private Serializable identificationKey;

        public LoginResult(Boolean isLoginPass, Integer permissionKey) {
            this.isLoginPass = isLoginPass;
            this.permissionKey = permissionKey;
            this.sessionMap = new HashMap<String, Object>();
        }

        public LoginResult(Boolean isLoginPass, Integer permissionKey, Serializable identificationKey) {
            this(isLoginPass, permissionKey);
            this.identificationKey = identificationKey;
        }

        public LoginResult addSessionAttribute(String key, Object value) {
            sessionMap.put(key, value);
            return this;
        }

        public Serializable getIdentificationKey() {
            return identificationKey;
        }

        public void setIdentificationKey(Serializable identificationKey) {
            this.identificationKey = identificationKey;
        }

        public Boolean getLoginPass() {
            return isLoginPass;
        }

        public void setLoginPass(Boolean loginPass) {
            isLoginPass = loginPass;
        }

        public Integer getPermissionKey() {
            return permissionKey;
        }

        public void setPermissionKey(Integer permissionKey) {
            this.permissionKey = permissionKey;
        }

        public Map<String, Object> getSessionMap() {
            return sessionMap;
        }

        public void setSessionMap(Map<String, Object> sessionMap) {
            this.sessionMap = sessionMap;
        }
    }
}
